{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Standard libraries"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Like pandapower, also pandapipes provides different standard libraries to simplify the workflow. In comparison with pandapower, pandapipes does not only provide a component library, but also a fluid library. After the pandapipes installation, this library already contains several fluids. Of course, it is also possible to define new fluids and add them to the library.\n",
    "\n",
    "This tutorial demonstrates the usage with the libraries and shows, how components and fluids can be loaded and saved. We start with a tutorial on the component library. This library contains pipes and pumps.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## pandapipes component library"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "With the function \"get_data\", which is defined in the module std_type_toolbox, all entries in the library can be displayed. Necessary parameters include the path to the library file and the type of the component. In the following section, the pipe entries are plotted. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "from pandapipes.std_types.std_type_class import get_data\n",
    "from pandapipes import pp_dir\n",
    "\n",
    "path = os.path.join(pp_dir, 'std_types/library/Pipe.csv')\n",
    "print(get_data(path, 'pipe'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The csv files can be extended. We will now create an example network using components from the library."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandapipes as pp\n",
    "net = pp.create_empty_network(fluid=\"water\")\n",
    "junction1 = pp.create_junction(net, pn_bar=1.0, tfluid_k=293.15, name=\"Connection to External Grid\")\n",
    "junction2 = pp.create_junction(net, pn_bar=1.0, tfluid_k=293.15, name=\"Junction\")\n",
    "junction3 = pp.create_junction(net, pn_bar=1.0, tfluid_k=293.15, name=\"Junction to sink\")\n",
    "medium_pressure_grid = pp.create_ext_grid(net, junction=junction1, p_bar=1, t_k=293.15, name=\"Grid Connection\")\n",
    "sink = pp.create_sink(net, junction=junction3, mdot_kg_per_s=23.05, name=\"Sink\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the code above, a pipe connection is missing between junction1 and junction2. We load the pipe type \"300_GGG\" from the library using the function \"create_pipe\". Compared to the function \"create_pipe_from_parameters\" a parameter with a library reference can be specified."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pipe1 = pp.create_pipe(net, from_junction=junction2, to_junction=junction3, length_km=1, std_type=\"300_GGG\", name=\"Pipe 1\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Between the external grid and the pipe, there is also a connection missing. This one will be defined using a pump component. The pressure difference is defined based on the underlying pump curve."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "P1 = pp.create_pump(net, from_junction=junction1, to_junction=junction2, std_type=\"P1\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The network can be computed as usual."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pp.pipeflow(net)\n",
    "net.res_pump"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The pump raises the pressure to 4 bar. We can check this by having a look at the pump curve."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "path = os.path.join(pp_dir, 'std_types/library/Pump/P1.csv')\n",
    "print(get_data(path, 'pump'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We notice that the pressure rais of 4 bar corresponds to a volume flow of 83 m^3/h. This volume flow is also defined at the sink."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## The fluid library"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the introductory example, the fluid is added via a parameter of the create_empty_network function. Internally, pandapipes fetches the corresponding fluid properties, which are saved for the specified fluid. Some of the predefined fluids are\n",
    "\n",
    "- air\n",
    "- hydrogen\n",
    "- lgas\n",
    "- hgas\n",
    "- water\n",
    "- methane\n",
    "\n",
    "For the calculation of pressure and flow velocity the density and viscosity has to be known. In case of gas calculations, these fluid properties can be dependend on temperature. If the temperature is calculated, further material properties may be needed, for example the heat capacity of the fluid.\n",
    "\n",
    "An overview of defined fluid properties is given in the directory pandapipes\\properties. In the directory of each fluid, you can find the fluid properties. Each property is described by a text file. This file contains data points. During the calculation, pandapipes interpolates between these points.\n",
    "\n",
    "If you want to know which properties are defined in the current net container, you can use the function get_property()."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "net.fluid.get_property(\"density\", 295)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The second parameter is the temperature, at which the density is displayed."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Defining new fluids"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "New fluids can be created or existing fluids modified. The mentioned fluids so far were dependent on temperature. We will now create an incompressible fluid with constant material properties and add it to the net.\n",
    "\n",
    "In a first step, the material properties are created. These properties are then added to a fluid container. The data structures used to describe properties and fluids are pythin classes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandapipes.properties.fluids as fl\n",
    "density_const = fl.FluidPropertyConstant(900)\n",
    "viscosity_const = fl.FluidPropertyConstant(0.002)\n",
    "heat_capacity_const = fl.FluidPropertyConstant(4000)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The three properties density, viscosity and heat capacity have to be defined. For every property, an object of the class FluidPropertyConstant is created and the constant property value is used in the object constructor. All properties have to be entered using SI units.\n",
    "\n",
    "Although constant properties are added here, pandapipes also provides classes for inter- and extrapolating properties.\n",
    "\n",
    "Afterwards, a fluid container is created and the properties are added."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "water_const =  fl.Fluid(\"water_const\",\"liquid\")\n",
    "water_const.add_property(property_name=\"density\",prop=density_const)\n",
    "water_const.add_property(property_name=\"viscosity\",prop=viscosity_const)\n",
    "water_const.add_property(property_name=\"heat_capacity\",prop= heat_capacity_const)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The fluid can now be used to calculate incompressible media. With the command ...:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fl._add_fluid_to_net(net,water_const)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "... the fluid is added to the net container. By plotting again the fluid properties, we see that the old fluid has been replaced. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "net.fluid"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
